import read from '../read.js'
import is from '../is.js'
import { error } from '../../output.js'

const token = (inputs) => {
  let current = null

  const next = () => {
    const token = current
    current = null
    return token || readNext()
  }

  const peek = () => {
    return current || (current = readNext())
  }

  const eof = () => {
    return peek() === null
  }

  const croak = inputs.croak

  const readNext = () => {
    read.while(inputs, is.whitespace)

    if (inputs.eof()) return null

    const ch = inputs.peek()

    if (is.comment(ch)) {
      read.comment(inputs)
      return readNext()
    }

    if (is.digit(ch)) {
      return read.number(inputs)
    }

    if (is.idStart(ch)) {
      return read.identifier(inputs)
    }

    if (ch === '"') {
      return read.literal(inputs)
    }

    if (is.punctuation(ch)) {
      return read.punctuation(inputs)
    }

    if (is.operator(ch)) {
      return read.operator(inputs)
    }

    if (is.dot(ch)) {
      return read.dot(inputs)
    }

    inputs.croak(`Can't handle character: ${ ch }`)
  }

  return {
    next,
    peek,
    eof,
    croak
  }
}

const toToken = (tokens) => {
  let index = 0

  const next = () => {
    return tokens[index++]
  }

  const peek = () => {
    return tokens[index]
  }

  const eof = () => {
    return peek() === undefined
  }

  const croak = msg => error(msg)

  return {
    next,
    peek,
    eof,
    croak
  }
}

export { toToken }
export default token
